package recom

import (
	"database/sql"
	"fmt"
	"sync"
	"time"
)

import (
	"github.com/denisenkom/go-mssqldb"
)

import (
	"buyChance"
	dbc "dbConnector"
	"r_log"
	"util"
)

type RecommenderStatus struct {
	PersonId  util.UserID
	KlineType util.Period
	FlowId    uint64
	InfoMsg   string
}

func (r *Recommender) SaveResults() {
	dbc.ServerLock.RLock()
	sl := make([]dbc.ServerInfo, 0, len(dbc.Servers.Account)) //数据库地址列表
	for _, si := range dbc.Servers.Account {
		sl = append(sl, *si)
	}
	dbc.ServerLock.RUnlock()

	var wg sync.WaitGroup
	for _, s := range sl {
		wg.Add(1)
		go func(server dbc.ServerInfo) {
			defer wg.Done()
			db := server.DB
			/*			db, err := server.InitSqlServer()
						if err != nil {
							r_log.Logger.Error("tp.SaveAccState(): %v", fmt.Errorf("initSqlServer(%v): %v", server, err))
							return
						}*/
			r.NewRLock.Lock()
			resData, _ := r.NewResults[server.DataBase]
			resInfo, _ := r.NewRInfos[server.DataBase]
			if resInfo == nil {
				resInfo = new([]RecommenderResultInfo)
			}
			r.NewRLock.Unlock()
			err := saveResults(db, *resData, *resInfo)
			if err != nil {
				r_log.Logger.Error("tp.SaveResults(): %v", fmt.Errorf("saveResults(%v): %v", server, err))
			}
			r.NewRLock.Lock()
			r.NewResults[server.DataBase] = new([]RecommenderResult)
			r.NewRInfos[server.DataBase] = new([]RecommenderResultInfo)
			r.NewRLock.Unlock()
			//			db.Close()
		}(s)
	}
	wg.Wait()
	if r.Tps.CaclTime%1000000 == 220000 {
		db := dbc.Servers.Statistic.DB
		/*		db, err := dbc.Servers.Statistic.InitSqlServer()
				if err != nil {
					r_log.Logger.Error("tp.SaveStatistic(): %v", fmt.Errorf("initSqlServer(%v): %v", dbc.Servers.Statistic, err))
					return
				}
				defer db.Close()*/
		r.SaveStatistic(db)
	}
}

func saveResults(db *sql.DB, rrs []RecommenderResult, rri []RecommenderResultInfo) error {
	if len(rri) == 0 {
		return nil
	}

	if len(rrs) == 0 {
		dbstring := `set xact_abort on
				begin tran
				Exec P_RecommenderServer_SaveInfo ?
				Exec P_RecommenderServer_UpDateCalsStatus ?
				commit tran `
		tvpType2 := mssql.TVPType{
			TVPTypeName: "RecommenderResultInfoType",
			TVPScheme:   "dbo",
			TVPValue:    rri,
		}
		var rss []RecommenderStatus
		for i := 0; i < len(rri); i++ {
			rs := RecommenderStatus{
				PersonId:  rri[i].UserId,
				KlineType: rri[i].Period,
				FlowId:    rri[i].FlowId,
				InfoMsg:   "股票分配成功",
			}
			switch rri[i].Info {
			case RI_HaveRecomm:
				rs.InfoMsg += "(股票已分配)"
			case RI_NORecomm:
				rs.InfoMsg += "(无推荐股票)"
			case RI_NOPosition:
				rs.InfoMsg += "(无仓位可加)"
			}
			rss = append(rss, rs)
		}
		tvpType3 := mssql.TVPType{
			TVPTypeName: "RecommenderResultCalcStatusType",
			TVPScheme:   "dbo",
			TVPValue:    rss,
		}

		_, err := db.Exec(dbstring, tvpType2, tvpType3)

		return err
	}

	dbstring := `set xact_abort on
				begin tran				
				Exec P_RecommenderServer_SaveInfo ?
				Exec P_RecommenderServer_SaveResult ?
				Exec P_RecommenderServer_UpDateCalsStatus ?
				commit tran`

	tvpType1 := mssql.TVPType{
		TVPTypeName: "RecommenderResultTableType",
		TVPScheme:   "dbo",
		TVPValue:    rrs,
	}

	tvpType2 := mssql.TVPType{
		TVPTypeName: "RecommenderResultInfoType",
		TVPScheme:   "dbo",
		TVPValue:    rri,
	}

	var rss []RecommenderStatus
	for i := 0; i < len(rri); i++ {
		rs := RecommenderStatus{
			PersonId:  rri[i].UserId,
			KlineType: rri[i].Period,
			FlowId:    rri[i].FlowId,
			InfoMsg:   "股票分配成功",
		}
		switch rri[i].Info {
		case RI_HaveRecomm:
			rs.InfoMsg += "(股票已分配)"
		case RI_NORecomm:
			rs.InfoMsg += "(无推荐股票)"
		case RI_NOPosition:
			rs.InfoMsg += "(无仓位可加)"
		}
		rss = append(rss, rs)
	}
	tvpType3 := mssql.TVPType{
		TVPTypeName: "RecommenderResultCalcStatusType",
		TVPScheme:   "dbo",
		TVPValue:    rss,
	}

	_, err := db.Exec(dbstring, tvpType2, tvpType1, tvpType3)

	return err
}

func (r *Recommender) SaveStatistic(db *sql.DB) {
	var ret []StatisticsSave
	bcb := &buyChance.BCBase
	for p := 0; p < 4; p++ {
		bcb.BcLock[p].Lock()
		SS := StatisticsSave{Date: int(r.Tps.Date), Period: int(p), CountOfGetStock: r.Statistic[p].CountOfGetStock,
			CountOfNotGetStock: r.Statistic[p].CountOfNotGetStock, CountOfBuyChance: 0}
		now := time.Now()
		date := util.Today()
		time := util.DateAndTime(now.Hour()*10000 + now.Minute()*100 + now.Second())
		ts := util.GeneratorTimestamp(date, time)
		if bcb.BuyChances[p].IsValid(ts, false) {
			SS.CountOfBuyChance = len(bcb.BuyChances[p].BcSlice)
		}
		ret = append(ret, SS)
		bcb.BcLock[p].Unlock()
	}
	dbstring := `Exec P_RecommenderServer_SaveStatistic ?`
	tvpType2 := mssql.TVPType{
		TVPTypeName: "Wealth_StatisticTableType",
		TVPScheme:   "dbo",
		TVPValue:    ret,
	}

	db.Exec(dbstring, tvpType2)

}
